/*-----------------------------------------------------------------------------
The contents of this file are subject to the Mozilla Public License
Version 1.1 (the "License"); you may not use this file except in
compliance with the License.You may obtain a copy of the License at
http://www.mozilla.org/MPL/MPL-1.1.html
	
Software distributed under the License is distributed on an "AS IS"
basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
License for the specific language governing rights and limitations
under the License.
	
The Original Code is Fever RS ( ActionScript 3 ) Framework code.
	
The Initial Developer of the Original Code is Romain Ecarnot.
Portions created by Initial Developer are Copyright (C) 2006
the Initial Developer. All Rights Reserved.
	
Contributor(s):
	
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-----------------------------------------------------------------------------*/

package fever.app.context.browser 
{
	import flash.display.StageDisplayState;
	import flash.events.Event;
	import flash.external.ExternalInterface;
	
	import com.bourre.collection.HashMap;
	import com.bourre.structures.Point;
	import com.bourre.structures.Rectangle;
	
	import fever.app.context.ApplicationContainer;
	import fever.app.context.abstract.AbstractContainer;
	import fever.commands.JSCommand;
	import fever.core.FeverCore;
	import fever.core.RSCore;
	import fever.core.fever_api;
	import fever.events.FeverEvent;
	import fever.log.FeverDebug;	
	/**
	 * <strong>Web browser</strong> container strategy.
	 * 
	 * @includeExample BrowserContainerSample.as -noswf
	 * 
	 * @see fever.app.context.ApplicationContainer
	 * @see fever.core.FeverCore
	 * 
	 * @author Romain Ecarnot
	 */
	public class BrowserContainer extends AbstractContainer 
		implements ApplicationContainer 
	{
		//--------------------------------------------------------------------
		// Private properties
		//--------------------------------------------------------------------
		
		//JS Command name
		private static var _setTitleMETHOD : String = "setTitle";
		private static var _getTitleMETHOD : String = "getTitle";
		private static var _setLocationMETHOD : String = "setLocation";
		private static var _getLocationMETHOD : String = "getLocation";
		private static var _setSizeMETHOD : String = "setSize";
		private static var _getURLMETHOD : String = "getURL";
		
		//JS Command list
		private var _setTitle : JSCommand;		private var _getTitle : JSCommand;		private var _setLocation : JSCommand;		private var _getLocation : JSCommand;
		private var _setSize : JSCommand;
		private var _getURL : JSCommand;
		
		private var _bIE : Boolean;
		private var _mURLArgs : HashMap;
		

		//--------------------------------------------------------------------
		// Public API
		//--------------------------------------------------------------------
		
		/**
		 * @private
		 * Constructor.
		 */
		public function BrowserContainer()
		{
			super( getConstructorAccess() );
			
			_checkIE();
			_initJSCommand();
			_parseArguments();
			
			RSCore.stage.addEventListener( Event.RESIZE, _onResize );
		}
		
		/** 
		 * @inheritDoc
		 */
		public function setTitle( mainTitle : String = null, 
			subTitle : String = null, historyCaption : String = null ) : void
		{
			var newTitle : String =	getFullFormattedTitle( 
				mainTitle, 
				subTitle, 
				historyCaption  
			);
			
			if ( newTitle != getTitle() )
			{
				_setTitle.call( newTitle );
				_dispatchAPIEvent( new FeverEvent( FeverEvent.onTitleChangeEVENT, this ) );
			}
		}
		
		/** 
		 * @inheritDoc
		 */
		public function getTitle() : String
		{
			return _getTitle.call().toString();
		}
		
		/** 
		 * @inheritDoc
		 */
		public function move( x : int, y : int ) : void
		{
			if( !isFullScreen() )
			{
				_setLocation.call( x, y );
				
				_dispatchAPIEvent( new FeverEvent( FeverEvent.onMoveEVENT, this ) );
			}
		}
		
		/** 
		 * @inheritDoc
		 */
		public function getLocation() : Point
		{
			var r : Object = _getLocation.call();
			return new Point( r.x, r.y );
		}
		
		/** 
		 * @inheritDoc
		 */
		public function setSize( width : int, height : int ) : void
		{
			if( !isFullScreen() )
			{
				_setSize.call( width, height );
			}
		}
		
		/** 
		 * @inheritDoc
		 */
		public function getSize() : Rectangle
		{
			var r : Object = _getLocation.call();
			
			return new Rectangle( 
				RSCore.stage.stageWidth, 
				RSCore.stage.stageHeight, 
				r.x, 
				r.y 
			);
		}
		
		/** 
		 * @inheritDoc
		 */
		public function setFullScreenMode( b : Boolean ) : void
		{
			RSCore.stage.displayState = ( b )
				? StageDisplayState.FULL_SCREEN
				: StageDisplayState.NORMAL;
			
			//TODO disptach FullScreenEvent.FULL_SCREEN
		}
		
		/** 
		 * @inheritDoc
		 */
		public function isFullScreen() : Boolean
		{
			return RSCore.stage.displayState == StageDisplayState.FULL_SCREEN;
		}
		
		/**
		 * Not available in Browser context.
		 * @inheritDoc
		 */
		public function maximize() : void {	}
		
		/**
		 * Not available in Browser context.
		 * @inheritDoc
		 */
		public function minimize() : void {	}
		
		/**
		 * Not available in Browser context.
		 * @inheritDoc
		 */
		public function restore() : void { }
		
		/** 
		 * @inheritDoc
		 */
		public function getArgument( id : String ) : String
		{
			if( _mURLArgs.containsKey( id ) )
			{
				return _mURLArgs.get( id );	
			}
			else return null;
		}
		
		
		//--------------------------------------------------------------------
		// Private implementations
		//--------------------------------------------------------------------
		
		private function _initJSCommand() : void
		{
			_setTitle = new JSCommand( 
				_setTitleMETHOD,
				"( s ){	document.title = s; }"
			);
			
			_getTitle = new JSCommand( 
				_getTitleMETHOD,
				"(){ return document.title; }"
			);
			
			_setLocation = new JSCommand(
				_setLocationMETHOD,
				"( x, y ){ window.moveTo( x, y );}"
			);
			
			var getLoc : String = "";
			getLoc += "(){";
			getLoc += ( _bIE )
				? "return { x : window.screenLeft, y : window.screenTop };"
				: "return { x : window.screenX, y : window.screenY };";
			getLoc += "}";
			_getLocation = new JSCommand( _getLocationMETHOD, getLoc );
			
			_setSize = new JSCommand(
				_setSizeMETHOD,
				"( w, h ){ window.resizeTo( w, h ); }"
			);
			
			_getURL = new JSCommand(
				_getURLMETHOD,
				"(){ return window.location.search;}"
			);
		}
		
		private function _checkIE() : void
		{
			if( ExternalInterface.available )
			{
				var f : String = "";
				f += "function getBrowserType( ){";
				f += "if ( navigator.plugins && navigator.mimeTypes && navigator.mimeTypes.length ) {";
				f += "return false;";
				f += "} else return true;";
				f += "}";
				
				ExternalInterface.call( "eval", f );
				_bIE = Boolean( ExternalInterface.call( "getBrowserType" ) );
			}
			else
			{
				_bIE = false;
				FeverDebug.ERROR( "External interface is " +
					"not available in current context" );
			}
		}

		private function _parseArguments() : void
		{
			_mURLArgs = new HashMap();
			
			//Parses loader arguments first
			var o : Object = RSCore.stage.loaderInfo.parameters;
			
			for ( var s : String in o )
			{
				_mURLArgs.put( 
						unescape( s ), unescape( o[s] ) 
					);	
			}
			
			//Parses url arguments now ( allow loader argument overloading )
			var url : String = String( _getURL.call() );
			if( url.length > 1 )
			{
				url = url.substr( 1 );
				var pair : Array = url.split( '&' );
				var pl : int = pair.length;
				
				for( var i : int = 0; i < pl; i++ )
				{
					var assos : Array = pair[i].split( '=' );
					_mURLArgs.put( 
						unescape( assos[0] ), unescape( assos[1] ) 
					);	
				}
			}
		}
		
		
		//--------------------------------------------------------------------
		// Private implementations
		//--------------------------------------------------------------------
		
		private function _onResize( event : Event ) : void
		{
			_dispatchAPIEvent( new FeverEvent( FeverEvent.onResizeEVENT, this ) );
		}
		
		private function _dispatchAPIEvent( event : Event = null ) : void
		{
			if( event != null )
			{
				RSCore.fever_api::fireAPIEvent( event );
			}
		}
	}
}
